import json
import copy
import time
from copy import deepcopy
from flask import Blueprint, request, jsonify
from controllers.common import *
from controllers.db import *
import logging
import pandas as pd
import requests

betting_event_project_api = Blueprint('betting_event_project_api', __name__)
betting_event_project_down_api = Blueprint('betting_event_project_down_api', __name__)
betting_event_schedule_api = Blueprint('betting_event_schedule_api', __name__)
betting_event_schedule_down_api = Blueprint('betting_event_schedule_down_api', __name__)
betting_event_schedule_timeline_api = Blueprint('betting_event_schedule_timeline_api', __name__)
betting_event_spider_api = Blueprint('betting_event_spider_api', __name__)
betting_event_world_cup_schedule_api = Blueprint('betting_event_world_cup_schedule_api', __name__)

USE_CMD_LOG = True

def betting_log(module_name, host, info):
    if USE_CMD_LOG is False:
        return
    print(f'[Betting] [{fomat_timestamp(int(time.time()))}] [Log] [{module_name}] host={host} - {info}', flush=True)

@betting_event_project_api.route('/betting_event_project', methods=['POST'])
def betting_event_project():
    params = json.loads(request.data)

    # host = request.host
    print(request.headers, flush=True)
    if 'X-Forwarded-For' in request.headers:
        host = request.headers['X-Forwarded-For']
    else:
        host = request.host

    _action = params['action']
    _project = params['project']
    result_data = {'status': 200, 'data': {'msg': '', 'ret': 0, 'type': 'success', 'env': EVN, 'item': ''}}
    if _action == 'view':
        betting_log('project', host, f'view project list')

        query = BettingEventProject.query.order_by('project').all()
        result = []
        for q in query:
            menu = json.loads(q.menu)
            tmp = {
                "project": int(q.project),
                'remark': q.remark
            }
            result.append(tmp)
        result_data['data']['item'] = result
    elif _action == 'detail':
        betting_log('project', host, f'view project detail project={_project}')
        query = BettingEventProject.query.filter_by(project=_project).first()
        menu = json.loads(query.menu)

        tmp = {
            "project": int(query.project),
            'menu': menu,
            'menu_stage': json.loads(query.menu_stage),
            'normal': json.loads(query.normal),
            'champion': json.loads(query.champion),
            'participant': json.loads(query.participant),
        }
        result_data['data']['item'] = tmp

    elif _action == 'doc_id_list':
        doc_file_data = GetDocByFilename('bet_event')
        result = []
        for k, v in doc_file_data.items():
            result.append({
                'value': int(k),
                'label': '{0}-{1}'.format(k, v['title'])
            })
        return json.dumps(result)

    elif _action == 'update_part':
        _data = params['data']
        _part = params['part']

        betting_log('project', host, f'update part project={_project}, part={_part}')

        if _part == 'menu':
            BettingEventProject.query.filter_by(project=_project).update({
                'menu': json.dumps(_data)
            })
        elif _part == 'menu_stage':
            BettingEventProject.query.filter_by(project=_project).update({
                'menu_stage': json.dumps(_data)
            })
        elif _part == 'normal_stage':
            project_data = BettingEventProject.query.filter_by(project=_project).first()
            _normal = json.loads(project_data.normal)
            _normal['normal_event_ui'] = _data['normal_event_ui']
            _normal['normal_doc_id'] = _data['normal_doc_id']
            _normal['is_show_stage_info'] = _data['is_show_stage_info']
            _normal['stage'] = _data['stage']
            BettingEventProject.query.filter_by(project=_project).update({
                'normal': json.dumps(_normal)
            })
        elif _part == 'normal_single':
            project_data = BettingEventProject.query.filter_by(project=_project).first()
            _normal = json.loads(project_data.normal)
            _normal['normal_single'] = _data
            BettingEventProject.query.filter_by(project=_project).update({
                'normal': json.dumps(_normal)
            })
        elif _part == 'champion_stage':
            project_data = BettingEventProject.query.filter_by(project=_project).first()
            _champion = json.loads(project_data.champion)
            _champion['champion_event_ui'] = _data['champion_event_ui']
            _champion['currency'] = _data['currency']
            _champion['limit'] = _data['limit']
            _champion['champion_doc_id'] = _data['champion_doc_id']
            _champion['limit_num'] = _data['limit_num']
            _champion['stage'] = _data['stage']
            BettingEventProject.query.filter_by(project=_project).update({
                'champion': json.dumps(_champion)
            })
        elif _part == 'participant':
            BettingEventProject.query.filter_by(project=_project).update({
                'participant': json.dumps(_data)
            })
        db.session.commit()
        result_data['data']['msg'] = "更新成功"
    elif _action == 'remark':
        betting_log('project', host, f'remark project={_project}')

        newRemark = params['remark']
        BettingEventProject.query.filter_by(project=_project).update({'remark': newRemark})
        db.session.commit()
        result_data['data']['msg'] = "Remark 更新成功"
    elif _action == 'clone':  # 克隆方案
        betting_log('project', host, f'clone from={_project}')

        betting_event_project_data = BettingEventProject.query.filter_by(project=_project).first()

        new_project_data = BettingEventProject(
            remark=betting_event_project_data.remark,
            menu=betting_event_project_data.menu,
            menu_stage=betting_event_project_data.menu_stage,
            normal=betting_event_project_data.normal,
            champion=betting_event_project_data.champion,
            participant=betting_event_project_data.participant
        )
        db.session.add(new_project_data)
        db.session.commit()
        new_project_id = new_project_data.project
        if new_project_id is None:
            result_data['status'] = 500
            result_data['data']['msg'] = "克隆失败：id is None"
        else:
            temp_data = BettingEventProject.query.filter_by(project=new_project_id).first()
            t_project = temp_data.project

            t_menu_stage = json.loads(temp_data.menu_stage)
            for i in range(len(t_menu_stage)):
                t_menu_stage[i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.menu_stage = json.dumps(t_menu_stage)

            t_normal = json.loads(temp_data.normal)
            for i in range(len(t_normal['normal_single'])):
                t_normal['normal_single'][i]['index'] = t_project * 1000 + (int(i) + 1)
            for i in range(len(t_normal['stage'])):
                t_normal['stage'][i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.normal = json.dumps(t_normal)

            t_champion = json.loads(temp_data.champion)
            for i in range(len(t_champion['stage'])):
                t_champion['stage'][i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.champion = json.dumps(t_champion)

            t_participant = json.loads(temp_data.participant)
            for i in range(len(t_participant)):
                t_participant[i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.participant = json.dumps(t_participant)

            db.session.commit()

            betting_log('project', host, f'clone to={new_project_id}')

            result_data['data']['msg'] = "克隆成功"
    elif _action == 'delete':
        betting_log('project', host, f'delete project={_project}')

        betting_event_project_data = BettingEventProject.query.filter_by(project=_project).first()
        db.session.delete(betting_event_project_data)
        db.session.commit()
        betting_event_project_data = BettingEventProject.query.filter_by(project=_project).first()
        if betting_event_project_data is not None:
            result_data['status'] = 500
            result_data['data']['msg'] = "删除失败：id is not None"
        else:
            result_data['data']['msg'] = "删除成功"
    elif _action == 'shop_name_list':
        with open(STATIC_PATH + 'shop_name.json', encoding='UTF-8') as f:
            data = json.load(f)
            _result = [{
                "label": '-1 - 不存在兑换商店',
                "value": -1
            }]
            shop_data = ShopProject.query.order_by('project').all()
            for i in data:
                _children = []
                for q in shop_data:
                    if q.shop_name == data[i]['shop_name']:
                        if q.remark is None:
                            _label = str(q.project)
                        else:
                            _label = '%s - %s' % (int(q.project), q.remark)
                        _children.append({
                            "value": int(q.project),
                            "label": _label
                        })
                _result.append({
                    "value": int(data[i]['shop_id']),
                    "label": '%s - %s' % (int(data[i]['shop_id']), data[i]['shop_name']),
                    "children": _children
                })
            return json.dumps(_result)
    elif _action == 'shop_reward_list':
        shop_id = params['shop_id']
        shop_data = ShopProject.query.filter_by(project=shop_id).first()
        _result = []
        if shop_data is not None:
            reward_list = json.loads(shop_data.goods)
        else:
            reward_list = []
        for i in reward_list:
            _reward = i['reward'][0]
            _reward['name'] = _reward['name'] + ' * ' + str(_reward['num'])
            _result.append({
                "value": _reward,
                "label": _reward['name']
            })
        return json.dumps(_result)
    elif _action == 'country_id_list':
        with open(STATIC_PATH + 'betting_country_id_list.json', encoding='UTF-8') as f:
            data = json.load(f)
            return json.dumps(data)
    elif _action == 'fix_project_id':
        project_data = BettingEventProject.query.order_by('project').all()
        for temp_data in project_data:
            t_project = temp_data.project

            t_menu_stage = json.loads(temp_data.menu_stage)
            for i in range(len(t_menu_stage)):
                t_menu_stage[i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.menu_stage = json.dumps(t_menu_stage)

            t_normal = json.loads(temp_data.normal)
            for i in range(len(t_normal['normal_single'])):
                t_normal['normal_single'][i]['index'] = t_project * 1000 + (int(i) + 1)
            for i in range(len(t_normal['stage'])):
                t_normal['stage'][i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.normal = json.dumps(t_normal)

            t_champion = json.loads(temp_data.champion)
            for i in range(len(t_champion['stage'])):
                t_champion['stage'][i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.champion = json.dumps(t_champion)

            t_participant = json.loads(temp_data.participant)
            for i in range(len(t_participant)):
                t_participant[i]['index'] = t_project * 1000 + (int(i) + 1)
            temp_data.participant = json.dumps(t_participant)

            db.session.commit()

        result_data['data']['msg'] = "处理成功"
    return jsonify(result_data)


@betting_event_project_down_api.route('/betting_event_project_down/<int:is_push>', methods=['GET', 'POST'])
def betting_event_project_down(is_push):
    host = request.host

    betting_log('project_download', host, f'is_push={is_push}')

    betting_menu_project = {}
    betting_menu_stage_project = {}
    betting_normal_project = {}
    betting_normal_stage_project = {}
    betting_normal_single_project = {}
    betting_champion_project = {}
    betting_champion_stage_project = {}

    query = BettingEventProject.query.order_by('project').all()

    shop_project_data = ShopProject.query.all()
    # shop_name_data = ShopName.query.all()
    shop_name_data = {}
    with open(STATIC_PATH + 'shop_name.json', encoding='utf8') as f:
        shop_name_data = json.load(f)

    for q in query:
        project = int(q.project)
        menu = json.loads(q.menu)
        menu_stage = json.loads(q.menu_stage)
        normal = json.loads(q.normal)
        champion = json.loads(q.champion)
        participant = json.loads(q.participant)

        if menu['exchange_shop'] == -1:
            _menu_reward = []
        else:
            _menu_reward = RewardToTMysqlNew(menu['reward'])

        menu_doc_id = menu['doc_id']
        normal_doc_id = normal['normal_doc_id']
        champion_doc_id = champion['champion_doc_id']

        _shop_id = -1
        _shop_name = ''
        for spd in shop_project_data:
            if spd.project == menu['exchange_shop']:
                _shop_name = spd.shop_name
                break
        if _shop_name != '':
            for sndindex in shop_name_data:
                snd = shop_name_data[sndindex]
                if snd['shop_name'] == _shop_name:
                    _shop_id = snd['shop_id']

        if 'calendar_doc_id' in menu:
            _calendar_doc_id = menu['calendar_doc_id']
        else:
            _calendar_doc_id = 1

        # 20221201 活动日历的event_ui和basic内的event_ui保持一致
        betting_menu_project[str(project)] = {
            'calendar_conf': {
                'event_type': 110,
                'event_ui': menu['event_ui'],
                'order': 1,
                'jump': 1,
                'localization': {
                    'title': _calendar_doc_id,
                    'info': _calendar_doc_id
                },
                'reward': _menu_reward,
                'show_type': 0
            },
            "basic": {
                "event_ui": menu['event_ui']
            },
            "localization_str": {},
            "localization_doc": {
                "title": menu_doc_id,
                "info": menu_doc_id,
                "content": menu_doc_id
            },
            # "exchange_shop": menu['exchange_shop'],
            "exchange_shop": _shop_id,
            "reward": _menu_reward
        }
        for i in menu_stage:
            betting_menu_stage_project[str(i['index'])] = {
                "basic": {
                    "event_ui": i['event_ui']
                },
                "localization_str": {},
                "localization_doc": {
                    "title": i['stage_doc_id'],
                    "content": i['stage_doc_id']
                }
            }

        if 'is_show_stage_info' in normal:
            is_show_stage_info = normal['is_show_stage_info']
        else:
            is_show_stage_info = 1
        betting_normal_project[str(project)] = {
            "basic": {
                "event_ui": normal['normal_event_ui']
            },
            "localization_str": {},
            "localization_doc": {
                "title": normal_doc_id,
                "info": normal_doc_id
            },
            "is_show_stage_info": is_show_stage_info
        }
        for i in normal['stage']:
            if 'normal_stage_doc_id' in i:
                normal_stage_doc_id = i['normal_stage_doc_id']
            else:
                normal_stage_doc_id = 1
            betting_normal_stage_project[str(i['index'])] = {
                "basic": {
                    "event_ui": i['event_ui']
                },
                "localization_str": {},
                "localization_doc": {
                    "title": normal_stage_doc_id
                }
            }
        for i in normal['normal_single']:
            _currency = RewardToTMysqlNew(i['currency'])
            for j in range(len(i['currency'])):
                i['currency'][j]['num'] = i['limit']
            _limit = RewardToTMysqlNew(i['currency'])
            print('Normal Single Debug:', project, i['index'], i, flush=True)
            betting_normal_single_project[str(i['index'])] = {
                "basic": {
                    "event_ui": i['single_event_ui']
                },
                "localization_str": {},
                "localization_doc": {
                    "title": normal_doc_id
                },
                "basic_raward_pool": RewardToTMysqlNew(i['basic_raward_pool']),
                "currency": _currency,
                'limit': _limit,
                "compensate_rate": i['compensate_rate'] * 100
            }
        _currency = RewardToTMysqlNew(champion['currency'])
        for j in range(len(champion['currency'])):
            champion['currency'][j]['num'] = champion['limit']
        _limit = RewardToTMysqlNew(champion['currency'])
        betting_champion_project[str(project)] = {
            "basic": {
                "event_ui": champion['champion_event_ui']
            },
            "localization_str": {},
            "localization_doc": {
                "title": champion_doc_id,
                "info": champion_doc_id
            },
            "limit": _limit,
            # "limit_num": 128
            "limit_num": champion['limit_num']
        }
        for i in champion['stage']:
            if 'champion_stage_doc_id' in i:
                champion_stage_doc_id = i['champion_stage_doc_id']
            else:
                champion_stage_doc_id = 1
            betting_champion_stage_project[str(i['index'])] = {
                "basic": {
                    "event_ui": i['event_ui']
                },
                "localization_str": {},
                "localization_doc": {
                    "title": champion_stage_doc_id,
                    "content": champion_stage_doc_id
                },
                "odds": i['odds'] * 100,
                "currency": _currency,
                "compensate_rate": i['compensate_rate'] * 100
            }
    if is_push == 2:
        response = DownLoad('betting_menu_project', betting_menu_project, 0)
    if is_push == 3:
        response = DownLoad('betting_menu_stage_project', betting_menu_stage_project, 0)
    if is_push == 4:
        response = DownLoad('betting_normal_project', betting_normal_project, 0)
    if is_push == 5:
        response = DownLoad('betting_normal_single_project', betting_normal_single_project, 0)
    if is_push == 6:
        response = DownLoad('betting_champion_project', betting_champion_project, 0)
    if is_push == 7:
        response = DownLoad('betting_champion_stage_project', betting_champion_stage_project, 0)
    if is_push == 8:
        response = DownLoad('betting_normal_stage_project', betting_normal_stage_project, 0)
    if is_push == 1:
        r1 = DownLoad('betting_menu_project', betting_menu_project, 1)
        r2 = DownLoad('betting_menu_stage_project', betting_menu_stage_project, 1)
        r3 = DownLoad('betting_normal_project', betting_normal_project, 1)
        r4 = DownLoad('betting_normal_single_project', betting_normal_single_project, 1)
        r5 = DownLoad('betting_champion_project', betting_champion_project, 1)
        r6 = DownLoad('betting_champion_stage_project', betting_champion_stage_project, 1)
        r7 = DownLoad('betting_normal_stage_project', betting_normal_stage_project, 1)
        if r1 and r2 and r3 and r4 and r5 and r6 and r7:
            return jsonify({"msg": "发布成功", "ret": 1})
        else:
            return False
    return response


@betting_event_schedule_api.route('/betting_event_schedule', methods=['POST'])
def betting_event_schedule():
    params = json.loads(request.data)
    host = request.host

    _action = params['action']
    _project = params['project']
    result_data = {'status': 200, 'data': {'msg': '', 'ret': 0, 'type': 'success', 'env': EVN, 'item': ''}}
    if _action == 'view':
        betting_log('schedule', host, f'view schedule list')

        query = BettingEventSchedule.query.order_by('project').all()
        result = []
        for q in query:
            tmp = {
                "project": int(q.project),
                'basic': json.loads(q.basic),
                'remark': q.remark,
                'publish': q.publish
            }
            result.append(tmp)
        result_data['data']['item'] = result
    elif _action == 'detail':
        betting_log('schedule', host, f'view schedule detail schedule={_project}')

        query = BettingEventSchedule.query.filter_by(project=_project).first()
        tmp = {
            "project": int(query.project),
            'basic': json.loads(query.basic),
            'normal': json.loads(query.normal),
            'champion': json.loads(query.champion)
        }
        result_data['data']['item'] = tmp
    elif _action == 'change_publish':
        _publish = params['value']

        betting_log('schedule', host, f'change schedule publish setting schedule={_project}, publish={_publish}')

        BettingEventSchedule.query.filter_by(project=_project).update({'publish': _publish})
        db.session.commit()
    elif _action == 'update_part':
        _data = params['data']
        _part = params['part']

        betting_log('schedule', host, f'update part schedule={_project}, part={_part}')

        if _part == 'basic':
            BettingEventSchedule.query.filter_by(project=_project).update({
                'basic': json.dumps(_data)
            })
        elif _part == 'normal':
            query = BettingEventSchedule.query.filter_by(project=_project).first()
            print(params)
            _index = _data['index']
            normal = json.loads(query.normal)
            normal[str(_index)] = _data['data']
            query.normal = json.dumps(normal)
        elif _part == 'champion':
            query = BettingEventSchedule.query.filter_by(project=_project).first()
            print(params)
            _index = _data['index']
            champion = json.loads(query.champion)
            champion[str(_index)] = _data['data']
            query.champion = json.dumps(champion)
        db.session.commit()
        result_data['data']['msg'] = "更新成功"
    elif _action == 'remark':
        betting_log('schedule', host, f'remark schedule={_project}')

        newRemark = params['remark']
        BettingEventSchedule.query.filter_by(project=_project).update({'remark': newRemark})
        db.session.commit()
        result_data['data']['msg'] = "Remark 更新成功"
    elif _action == 'clone':  # 克隆方案
        betting_log('schedule', host, f'clone from={_project}')

        betting_event_schedule_data = BettingEventSchedule.query.filter_by(project=_project).first()

        # 20221027 克隆时去除竞赛者和冠军配置
        basic = json.loads(betting_event_schedule_data.basic)
        basic['champion_schedule']['champion'] = -1
        basic['champion_schedule']['participant'] = []
        champion = json.loads(betting_event_schedule_data.champion)
        for i in champion:
            champion[i]['participant'] = []
            champion[i]['knockout'] = []
        normal = json.loads(betting_event_schedule_data.normal)
        for i in normal:
            for j in range(len(normal[i]['single'])):
                normal[i]['single'][j]['result'] = {
                    "left_score": "",
                    "result_type": 0,
                    "right_score": ""
                }

        new_project_data = BettingEventSchedule(
            remark=betting_event_schedule_data.remark,
            basic=json.dumps(basic),
            normal=json.dumps(normal),
            champion=json.dumps(champion),
            max_stage=betting_event_schedule_data.max_stage,
            publish=betting_event_schedule_data.publish
        )
        db.session.add(new_project_data)
        db.session.commit()
        new_project_id = new_project_data.project
        if new_project_id is None:
            result_data['status'] = 500
            result_data['data']['msg'] = "克隆失败：id is None"
        else:
            betting_log('schedule', host, f'clone to={new_project_id}')

            result_data['data']['msg'] = "克隆成功"
    elif _action == 'delete':
        betting_log('schedule', host, f'delete schedule={_project}')

        betting_event_schedule_data = BettingEventSchedule.query.filter_by(project=_project).first()
        db.session.delete(betting_event_schedule_data)
        db.session.commit()
        betting_event_schedule_data = BettingEventSchedule.query.filter_by(project=_project).first()
        if betting_event_schedule_data is not None:
            result_data['status'] = 500
            result_data['data']['msg'] = "删除失败：id is not None"
        else:
            result_data['data']['msg'] = "删除成功"
    elif _action == 'add':
        new_project_data = BettingEventSchedule(
            remark='',
            basic=json.dumps(
                {"event_id": "", "forecast_time": "", "begin_time": "", "close_time": "", "pid": "", "sid_list": "",
                 "normal_schedule": {"enable": False, "event_id": "", "forecast_time": "", "begin_time": "",
                                     "close_time": ""},
                 "champion_schedule": {"enable": False, "event_id": "", "forecast_time": "", "begin_time": "",
                                       "close_time": "", "champion": -1, "participant": []},
                 "stage": []}),
            normal=json.dumps({}),
            champion=json.dumps({}),
            max_stage=0,
            publish=0
        )
        db.session.add(new_project_data)
        db.session.commit()
        new_project_id = new_project_data.project
        if new_project_id is None:
            result_data['status'] = 500
            result_data['data']['msg'] = "新增失败：id is None"
        else:
            betting_log('schedule', host, f'add schedule={new_project_id}')
            result_data['data']['msg'] = "新增成功"
    elif _action == 'gen_stage':
        query = BettingEventSchedule.query.filter_by(project=_project).first()
        max_stage = query.max_stage
        BettingEventSchedule.query.filter_by(project=_project).update({
            "max_stage": max_stage + 1
        })
        return str(max_stage + 1)
    elif _action == 'get_normal':
        query = BettingEventSchedule.query.filter_by(project=_project).first()
        _index = params['index']

        betting_log('schedule', host, f'get normal detail schedule={_project}, index={_index}')

        normal = json.loads(query.normal)
        if str(_index) in normal:
            return json.dumps(normal[str(_index)])
        else:
            return json.dumps({
                "event_id": "",
                "pid": "",
                "can_draw": 0,
                "single": []
            })
    elif _action == 'get_champion':
        query = BettingEventSchedule.query.filter_by(project=_project).first()
        _index = params['index']

        betting_log('schedule', host, f'get champion detail schedule={_project}, index={_index}')

        champion = json.loads(query.champion)
        if str(_index) in champion:
            return json.dumps(champion[str(_index)])
        else:
            return json.dumps({
                "event_id": "",
                "pid": "",
                "participant": [],
                "knockout": []
            })
    elif _action == 'project_list':
        query = BettingEventProject.query.order_by('project').all()
        result = []
        for q in query:
            result.append({
                "value": int(q.project),
                "label": "%s - %s" % (int(q.project), q.remark)
            })
        return json.dumps(result)
    elif _action == 'normal_project_list':
        query = BettingEventProject.query.filter_by(project=_project).first()
        if query is None:
            return json.dumps([])
        result = []
        normal = json.loads(query.normal)
        for i in normal['stage']:
            result.append({
                "value": int(i['index']),
                "label": "%s - %s" % (int(i['index']), i['remark'])
            })
        return json.dumps(result)
    elif _action == 'champion_project_list':
        print(_project)
        query = BettingEventProject.query.filter_by(project=_project).first()
        if query is None:
            return json.dumps([])
        result = []
        champion = json.loads(query.champion)
        for i in champion['stage']:
            result.append({
                "value": int(i['index']),
                "label": "%s - %s" % (int(i['index']), i['remark'])
            })
        print(result)
        return json.dumps(result)
    elif _action == 'single_project_list':
        query = BettingEventProject.query.filter_by(project=_project).first()
        result = []
        normal = json.loads(query.normal)
        for i in normal['normal_single']:
            result.append({
                "value": int(i['index']),
                "label": "%s" % (int(i['index']))
            })
        return json.dumps(result)
    elif _action == 'check_before_public':
        _skip = params['skip']

        betting_log('schedule', host, f'begin check schedule={_project}, skip={_skip}')

        def genFailMessage(msg):
            return json.dumps({
                "status": "fail",
                "msg": msg
            })

        try:
            if _project == -1:
                if _skip:
                    project_data = BettingEventSchedule.query.order_by('project').filter_by(publish=1).all()
                else:
                    project_data = BettingEventSchedule.query.order_by('project').all()
            else:
                if _skip:
                    project_data = BettingEventSchedule.query.filter_by(project=_project, publish=1).all()
                else:
                    project_data = BettingEventSchedule.query.filter_by(project=_project).all()
            for current_project in project_data:
                project = int(current_project.project)
                basic = json.loads(current_project.basic)
                normal = json.loads(current_project.normal)
                champion = json.loads(current_project.champion)

                # 校验 竞猜主页总排期 该设置的都设置
                for i in ['forecast_time', 'begin_time', 'end_time', 'close_time', 'pid', 'sid_list']:
                    if basic[i] == '':
                        return genFailMessage("[PID=%s] 竞猜主页总排期 未配置 %s" % (project, i))

                # 校验 竞猜主页总排期 选择的pid存在
                _tmp_project = BettingEventProject.query.filter_by(project=basic['pid']).first()
                if _tmp_project is None:
                    return genFailMessage("[PID=%s] 竞猜主页总排期 无法找到 pid=%s 对应的方案" % (project, basic['pid']))

                # 校验 sid_list 可以被解析
                try:
                    _tmp_sid_list = ToSidList(basic['sid_list'])
                except:
                    return genFailMessage("[PID=%s] 竞猜主页总排期 无法解析 sid_list=%s" % (project, basic['sid_list']))

                # 校验 总排期4个时间按顺序
                check_list = ['forecast_time', 'begin_time', 'end_time', 'close_time']
                for i in range(1, 4):
                    if fomat_date_str(basic[check_list[i]]) < fomat_date_str(basic[check_list[i - 1]]):
                        return genFailMessage("[PID=%s] 竞猜主页总排期 %s(%s) < %s(%s)" % (
                            project, check_list[i], basic[check_list[i]], check_list[i - 1], basic[check_list[i - 1]]))

                if basic['champion_schedule']['enable']:
                    # 校验 冠军排期 forecast_time <= begin_time <= end_time
                    if fomat_date_str(basic['champion_schedule']['begin_time']) < fomat_date_str(
                            basic['forecast_time']):
                        return genFailMessage("[PID=%s] 冠军竞猜总排期 begin_time(%s) < forecast_time(%s)" % (
                            project, basic['champion_schedule']['begin_time'], basic['forecast_time']))
                    if fomat_date_str(basic['champion_schedule']['begin_time']) > fomat_date_str(basic['end_time']):
                        return genFailMessage("[PID=%s] 冠军竞猜总排期 begin_time(%s) > end_time(%s)" % (
                            project, basic['champion_schedule']['begin_time'], basic['end_time']))

                    # 校验 冠军 在参赛者中
                    if basic['champion_schedule']['champion'] not in basic['champion_schedule']['participant'] and \
                            basic['champion_schedule']['champion'] != -1:
                        return genFailMessage("[PID=%s] 冠军竞猜总排期 冠军(%s) 不在竞赛者列表中" % (
                            project, basic['champion_schedule']['champion']))

                    # 校验 参赛者有配置权重
                    participant_list = json.loads(_tmp_project.participant)
                    for i in basic['champion_schedule']['participant']:
                        pd = False
                        for j in participant_list:
                            if j['id'] == i:
                                pd = True
                                break
                        if pd is False:
                            return genFailMessage("[PID=%s] 冠军竞猜总排期 参赛者(%s) 未在方案中配置权重" % (
                                project, i))
                for stage_index in range(len(basic['stage'])):  # 主页竞猜阶段
                    stage = basic['stage'][stage_index]

                    # 校验 阶段project id 存在
                    _current_stage_project_id = stage['pid']
                    menu_stage = json.loads(_tmp_project.menu_stage)
                    pd = False
                    for i in menu_stage:
                        if i['index'] == _current_stage_project_id:
                            pd = True
                            break
                    if pd is False:
                        return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 无法找到 pid=%s 对应的阶段" % (
                            project, stage_index + 1, _current_stage_project_id))

                    # 校验 阶段时间符合要求
                    check_list = ['forecast_time', 'begin_time', 'end_time', 'close_time']
                    for i in range(1, 4):
                        if fomat_date_str(stage[check_list[i]]) < fomat_date_str(stage[check_list[i - 1]]):
                            return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 %s(%s) < %s(%s)" % (
                                project, stage_index + 1, check_list[i], stage[check_list[i]], check_list[i - 1],
                                stage[check_list[i - 1]]))
                    if fomat_date_str(stage['forecast_time']) < fomat_date_str(basic['begin_time']):
                        return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 forecast_time(%s) < 总排期begin_time(%s)" % (
                            project, stage_index + 1, stage['forecast_time'], basic['begin_time']))
                    if fomat_date_str(stage['close_time']) > fomat_date_str(basic['end_time']):
                        return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 close_time(%s) > 总排期end_time(%s)" % (
                            project, stage_index + 1, stage['close_time'], basic['end_time']))
                    if basic['champion_schedule']['enable'] and stage['enable_champion']:
                        if fomat_date_str(stage['forecast_time']) < fomat_date_str(
                                basic['champion_schedule']['begin_time']):
                            return genFailMessage(
                                "[PID=%s] 主页竞猜阶段 第%s行 (启用冠军竞猜) forecast_time(%s) < 冠军竞猜总排期begin_time(%s)" % (
                                    project, stage_index + 1, stage['forecast_time'],
                                    basic['champion_schedule']['begin_time']))
                    '''if stage_index != 0:
                        if fomat_date_str(stage['forecast_time']) < fomat_date_str(basic['stage'][stage_index - 1]['close_time']):
                            return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 forecast_time(%s) < 上一阶段close_time(%s)" % (
                                project, stage_index + 1, stage['forecast_time'], basic['stage'][stage_index - 1]['close_time']))'''
                    # 20221027 优化需求：forecast_time要等于上一阶段close_time
                    if stage_index != 0:
                        if fomat_date_str(stage['forecast_time']) != fomat_date_str(
                                basic['stage'][stage_index - 1]['close_time']):
                            return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 forecast_time(%s) != 上一阶段close_time(%s)" % (
                                project, stage_index + 1, stage['forecast_time'],
                                basic['stage'][stage_index - 1]['close_time']))

                    # 校验 启用普通阶段时配置了普通阶段数据
                    if basic['normal_schedule']['enable'] and stage['enable_normal']:
                        if str(stage['index']) not in normal:
                            return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 启用了普通阶段而未配置相关数据" % (
                                project, stage_index + 1))
                        normal_stage = normal[str(stage['index'])]
                        normal_stage_pid = normal_stage['pid']
                        # 校验 普通阶段pid 是否存在
                        _tmp_normal_data = json.loads(_tmp_project.normal)
                        pd = False
                        for i in _tmp_normal_data['stage']:
                            if i['index'] == normal_stage_pid:
                                pd = True
                                break
                        if pd is False:
                            return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 普通阶段 无法找到 pid=%s 对应的阶段" % (
                                project, stage_index + 1, normal_stage_pid))

                        for j in range(len(normal_stage['single'])):
                            normal_single = normal_stage['single'][j]
                            # 校验 普通单局竞猜 奖池pid存在
                            pd = False
                            for i in _tmp_normal_data['normal_single']:
                                if i['index'] == normal_single['pid']:
                                    pd = True
                                    break
                            if pd is False:
                                return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 普通阶段 单局竞猜 第%s行 无法找到 pid=%s 对应的奖池" % (
                                    project, stage_index + 1, j + 1, normal_single['pid']))

                            # 校验 单局竞猜4个时间按顺序
                            check_list = ['forecast_time', 'begin_time', 'end_time', 'close_time']
                            for i in range(1, 4):
                                if fomat_date_str(normal_single[check_list[i]]) < fomat_date_str(
                                        normal_single[check_list[i - 1]]):
                                    return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 单局竞猜 第%s行 %s(%s) < %s(%s)" % (
                                        project, stage_index + 1, j + 1, check_list[i], normal_single[check_list[i]],
                                        check_list[i - 1],
                                        normal_single[check_list[i - 1]]))
                            if fomat_date_str(normal_single['forecast_time']) < fomat_date_str(
                                    stage['forecast_time']):
                                return genFailMessage(
                                    "[PID=%s] 主页竞猜阶段 第%s行 单局竞猜 第%s行 forecast_time(%s) < 阶段forecast_time(%s)" % (
                                        project, stage_index + 1, j + 1, normal_single['forecast_time'],
                                        stage['forecast_time']))
                            if fomat_date_str(normal_single['close_time']) > fomat_date_str(
                                    stage['close_time']):
                                return genFailMessage(
                                    "[PID=%s] 主页竞猜阶段 第%s行 单局竞猜 第%s行 close_time(%s) > 阶段close_time(%s)" % (
                                        project, stage_index + 1, j + 1, normal_single['close_time'],
                                        stage['close_time']))

                    # 校验 启用冠军阶段时配置了冠军阶段数据
                    if basic['champion_schedule']['enable'] and stage['enable_champion']:
                        if str(stage['index']) not in champion:
                            return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 启用了冠军阶段而未配置相关数据" % (
                                project, stage_index + 1))
                        champion_stage = champion[str(stage['index'])]
                        champion_stage_pid = champion_stage['pid']
                        # 校验 冠军阶段pid 是否存在
                        _tmp_champion_data = json.loads(_tmp_project.champion)
                        pd = False
                        for i in _tmp_champion_data['stage']:
                            if i['index'] == champion_stage_pid:
                                pd = True
                                break
                        if pd is False:
                            return genFailMessage("[PID=%s] 主页竞猜阶段 第%s行 冠军阶段 无法找到 pid=%s 对应的阶段" % (
                                project, stage_index + 1, champion_stage_pid))

        except Exception as e:
            logging.exception(e)
            print('\033[31m[ERROR] [check_before_public]', e, '\033[0m')
            return json.dumps({
                "status": "fail",
                "msg": "意外错误"
            })
        return json.dumps({
            "status": "success",
            "msg": "校验成功"
        })
    elif _action == 'stage_clone':
        _oldIndex = params['oldIndex']
        _newIndex = params['newIndex']

        betting_log('schedule', host, f'clone stage schedule={_project}, old={_oldIndex}, new={_newIndex}')

        query = BettingEventSchedule.query.filter_by(project=_project).first()
        normal = json.loads(query.normal)
        if str(_oldIndex) in normal:
            normal[str(_newIndex)] = deepcopy(normal[str(_oldIndex)])
            query.normal = json.dumps(normal)
        champion = json.loads(query.champion)
        if str(_oldIndex) in champion:
            champion[str(_newIndex)] = deepcopy(champion[str(_oldIndex)])
            query.champion = json.dumps(champion)
        db.session.commit()

    elif _action == 'stage_list':
        query = BettingEventProject.query.filter_by(project=_project).first()
        result = []
        menu_stage = json.loads(query.menu_stage)
        for i in menu_stage:
            result.append({
                "value": int(i['index']),
                "label": "%s - %s" % (int(i['index']), i['remark'])
            })
        return json.dumps(result)
    elif _action == 'country_id_list':
        with open(STATIC_PATH + 'betting_country_id_list.json', encoding='UTF-8') as f:
            data = json.load(f)
            return json.dumps(data)
    return jsonify(result_data)


@betting_event_schedule_down_api.route('/betting_event_schedule_down/<int:is_push>', methods=['GET', 'POST'])
def betting_event_schedule_down(is_push):
    host = request.host
    betting_log('schedule_download', host, f'is_push={is_push}')

    with open(STATIC_PATH + 'betting_country_id_list.json', encoding='UTF-8') as f:
        country_id_list = json.load(f)

    def get_country_info(country_list, country_id):
        for i in country_list:
            if i['id'] == country_id:
                return i
        return {
            "id": -1,
            "index": -1,
            "order": -1,
            "type": 0
        }

    def get_country_name(country_id):
        for i in country_id_list:
            if i['value'] == country_id:
                return i['label']
        return 'unknown'

    betting_menu_schedule = []
    betting_menu_stage_schedule = []
    betting_normal_schedule = []
    betting_normal_stage_schedule = []
    betting_normal_single_schedule = []
    betting_normal_single_participant = {}
    betting_normal_single_result = {}
    betting_champion_schedule = []
    betting_champion_participant = {}
    betting_champion_result = {}
    betting_champion_stage_schedule = []
    betting_champion_stage_result = {}

    query = BettingEventSchedule.query.order_by('project').filter_by(publish=1).all()

    for q in query:
        project = int(q.project)

        basic = json.loads(q.basic)
        normal = json.loads(q.normal)
        champion = json.loads(q.champion)

        project_data = BettingEventProject.query.filter_by(project=basic['pid']).first()
        participant = json.loads(project_data.participant)

        _menu_forecast_time = fomat_date_str(basic['forecast_time'])
        _menu_begin_time = fomat_date_str(basic['begin_time'])
        _menu_end_time = fomat_date_str(basic['end_time'])
        _menu_close_time = fomat_date_str(basic['close_time'])
        _menu_pid = basic['pid']
        _menu_sid_list = ToSidList(basic['sid_list'])
        _menu_event_id = "%s_%s_%s_%s" % (110, _menu_forecast_time, _menu_sid_list[0], _menu_pid)
        _tmp_basic = {
            "forecast_time": _menu_forecast_time,
            "begin_time": _menu_begin_time,
            "end_time": _menu_end_time,
            "close_time": _menu_close_time,
            "pid": _menu_pid,
            "sid_list": _menu_sid_list
        }
        _tmp_betting_menu_schedule = deepcopy(_tmp_basic)
        _tmp_betting_menu_schedule['event_id'] = _menu_event_id
        _tmp_betting_menu_schedule['event_type'] = 110
        _tmp_betting_menu_schedule['calendar_conf'] = {
            "begin_time": _menu_begin_time,
            "end_time": _menu_end_time
        }
        betting_menu_schedule.append(_tmp_betting_menu_schedule)

        enable_normal = basic['normal_schedule']['enable']
        enable_champion = basic['champion_schedule']['enable']
        if enable_normal:
            _normal_event_id = "%s_%s_%s_%s" % (114, _menu_forecast_time, _menu_sid_list[0], _menu_pid)
            _tmp_betting_normal_schedule = deepcopy(_tmp_basic)
            _tmp_betting_normal_schedule['event_id'] = _normal_event_id
            _tmp_betting_normal_schedule['menu_event_id'] = _menu_event_id
            _tmp_betting_normal_schedule['event_type'] = 114
            betting_normal_schedule.append(_tmp_betting_normal_schedule)
        if enable_champion:
            _champion_begin_time = fomat_date_str(basic['champion_schedule']['begin_time'])
            _champion_event_id = "%s_%s_%s_%s" % (112, _menu_forecast_time, _menu_sid_list[0], _menu_pid)
            _tmp_betting_champion_schedule = deepcopy(_tmp_basic)
            _tmp_betting_champion_schedule['event_id'] = _champion_event_id
            _tmp_betting_champion_schedule['menu_event_id'] = _menu_event_id
            _tmp_betting_champion_schedule['event_type'] = 112
            _tmp_betting_champion_schedule['begin_time'] = _champion_begin_time
            betting_champion_schedule.append(_tmp_betting_champion_schedule)
            _participant = {}
            for i in basic['champion_schedule']['participant']:
                _participant['0_' + str(i)] = {
                    "basic_info": [0, i, get_country_info(participant, i)['order']]
                }
            if len(_participant) > 0:
                betting_champion_participant[_champion_event_id] = {
                    "participant": _participant
                }
            if basic['champion_schedule']['champion'] != -1:
                betting_champion_result[_champion_event_id] = {
                    "champion": "0_" + str(basic['champion_schedule']['champion'])
                }
        for stage in basic['stage']:
            _stage_forecast_time = fomat_date_str(stage['forecast_time'])
            _stage_begin_time = fomat_date_str(stage['begin_time'])
            _stage_end_time = fomat_date_str(stage['end_time'])
            _stage_close_time = fomat_date_str(stage['close_time'])
            _stage_pid = stage['pid']
            stage_index = stage['index']
            stage_enable_normal = stage['enable_normal']
            stage_enable_champion = stage['enable_champion']
            _stage_event_id = "%s_%s_%s_%s" % (111, _stage_forecast_time, _menu_sid_list[0], _stage_pid)
            betting_menu_stage_schedule.append({
                "event_id": _stage_event_id,
                "menu_event_id": _menu_event_id,
                "event_type": 111,
                "forecast_time": _stage_forecast_time,
                "begin_time": _stage_forecast_time,
                "end_time": _stage_close_time,
                "close_time": _stage_close_time,
                "pid": _stage_pid,
                "sid_list": _menu_sid_list
            })
            if enable_normal and stage_enable_normal:
                normal_data = normal[str(stage_index)]
                _normal_stage_pid = normal_data['pid']
                _normal_stage_event_id = "%s_%s_%s_%s" % (
                    115, _stage_forecast_time, _menu_sid_list[0], _normal_stage_pid)
                betting_normal_stage_schedule.append({
                    "event_id": _normal_stage_event_id,
                    "menu_event_id": _menu_event_id,
                    "main_event_id": _normal_event_id,
                    "event_type": 115,
                    "forecast_time": _stage_forecast_time,
                    "begin_time": _stage_forecast_time,
                    "end_time": _stage_close_time,
                    "close_time": _stage_close_time,
                    "pid": _normal_stage_pid,
                    "sid_list": _menu_sid_list
                })
                for single_index in range(len(normal_data['single'])):
                    single = normal_data['single'][single_index]
                    _single_event_id = "%s_%s_%s_%s_%s" % (
                        116, fomat_date_str(single['forecast_time']), _menu_sid_list[0], single['pid'], single_index)
                    betting_normal_single_schedule.append({
                        "event_id": _single_event_id,
                        "menu_event_id": _menu_event_id,
                        "main_event_id": _normal_event_id,
                        # "stage_event_id": _stage_event_id,
                        "stage_event_id": _normal_stage_event_id,
                        "event_type": 116,
                        "forecast_time": fomat_date_str(single['forecast_time']),
                        "begin_time": fomat_date_str(single['begin_time']),
                        "end_time": fomat_date_str(single['end_time']),
                        "close_time": fomat_date_str(single['close_time']),
                        "pid": single['pid'],
                        "sid_list": _menu_sid_list
                    })
                    betting_normal_single_participant[_single_event_id] = {
                        "participant": {
                            '0_' + str(single['left_country']): {
                                "type": 0,
                                "id": single['left_country'],
                                "side": 0
                            },
                            '0_' + str(single['right_country']): {
                                "type": 0,
                                "id": single['right_country'],
                                "side": 1
                            }
                        },
                        "schedule": {
                            "begin_time": fomat_date_str(single['begin_time'])
                        },
                        "can_draw": normal_data['can_draw']
                    }
                    if single['result']['left_score'] != '':
                        betting_normal_single_result[_single_event_id] = {
                            "detail": {
                                '0_' + str(single['left_country']): {
                                    "score": single['result']['left_score']
                                },
                                '0_' + str(single['right_country']): {
                                    "score": single['result']['right_score']
                                }
                            },
                            "result_type": single['result']['result_type']
                        }
            if enable_champion and stage_enable_champion:
                champion_data = champion[str(stage_index)]
                _champion_stage_pid = champion_data['pid']
                _champion_stage_event_id = "%s_%s_%s_%s" % (
                    113, _stage_forecast_time, _menu_sid_list[0], _champion_stage_pid)
                betting_champion_stage_schedule.append({
                    "event_id": _champion_stage_event_id,
                    "menu_event_id": _menu_event_id,
                    "main_event_id": _champion_event_id,
                    "event_type": 113,
                    "forecast_time": fomat_date_str(stage['forecast_time']),
                    "begin_time": fomat_date_str(stage['begin_time']),
                    "end_time": fomat_date_str(stage['end_time']),
                    "close_time": fomat_date_str(stage['close_time']),
                    "pid": _champion_stage_pid,
                    "sid_list": _menu_sid_list
                })
                if len(champion_data['knockout']) > 0:
                    _knockout = []
                    for j in champion_data['knockout']:
                        _knockout.append('0_' + str(j))
                    betting_champion_stage_result[_champion_stage_event_id] = {
                        "Knockout": _knockout
                    }

    if is_push == 2:
        response = DownLoad('betting_menu_schedule', betting_menu_schedule, 0)
    if is_push == 3:
        response = DownLoad('betting_menu_stage_schedule', betting_menu_stage_schedule, 0)
    if is_push == 4:
        response = DownLoad('betting_normal_schedule', betting_normal_schedule, 0)
    if is_push == 5:
        response = DownLoad('betting_normal_single_schedule', betting_normal_single_schedule, 0)
    if is_push == 6:
        response = DownLoad('betting_normal_single_participant', betting_normal_single_participant, 0)
    if is_push == 7:
        response = DownLoad('betting_normal_single_result', betting_normal_single_result, 0)
    if is_push == 8:
        response = DownLoad('betting_normal_stage_schedule', betting_normal_stage_schedule, 0)
    if is_push == 9:
        response = DownLoad('betting_champion_schedule', betting_champion_schedule, 0)
    if is_push == 10:
        response = DownLoad('betting_champion_participant', betting_champion_participant, 0)
    if is_push == 11:
        response = DownLoad('betting_champion_result', betting_champion_result, 0)
    if is_push == 12:
        response = DownLoad('betting_champion_stage_schedule', betting_champion_stage_schedule, 0)
    if is_push == 13:
        response = DownLoad('betting_champion_stage_result', betting_champion_stage_result, 0)
    if is_push == 1:
        r1 = DownLoad('betting_menu_schedule', betting_menu_schedule, 1)
        r2 = DownLoad('betting_menu_stage_schedule', betting_menu_stage_schedule, 1)
        r3 = DownLoad('betting_normal_schedule', betting_normal_schedule, 1)
        r4 = DownLoad('betting_normal_single_schedule', betting_normal_single_schedule, 1)
        r5 = DownLoad('betting_normal_single_participant', betting_normal_single_participant, 1)
        r6 = DownLoad('betting_normal_single_result', betting_normal_single_result, 1)
        r7 = DownLoad('betting_normal_stage_schedule', betting_normal_stage_schedule, 1)
        r8 = DownLoad('betting_champion_schedule', betting_champion_schedule, 1)
        r9 = DownLoad('betting_champion_participant', betting_champion_participant, 1)
        r10 = DownLoad('betting_champion_result', betting_champion_result, 1)
        r11 = DownLoad('betting_champion_stage_schedule', betting_champion_stage_schedule, 1)
        r12 = DownLoad('betting_champion_stage_result', betting_champion_stage_result, 1)
        if r1 and r2 and r3 and r4 and r5 and r6 and r7 and r8 and r9 and r10 and r11 and r12:
            return jsonify({"msg": "发布成功", "ret": 1})
        else:
            return False
    return response


@betting_event_schedule_timeline_api.route('/betting_event_schedule_timeline/<int:project>/', methods=['GET', 'POST'])
@betting_event_schedule_timeline_api.route('/betting_event_schedule_timeline/<int:project>', methods=['GET', 'POST'])
def betting_event_schedule_timeline(project):
    host = request.host
    betting_log('schedule_timeline', host, f'schedule={project}')

    project_data = BettingEventSchedule.query.filter_by(project=project).first()
    basic = json.loads(project_data.basic)
    normal = json.loads(project_data.normal)
    champion = json.loads(project_data.champion)

    timepoint = []
    time_field_list = ['forecast_time', 'begin_time', 'end_time', 'close_time']
    time_field_map = {
        'forecast_time': 'f',
        'begin_time': 'b',
        'end_time': 'e',
        'close_time': 'c'
    }
    # 主排期时间
    for i in time_field_list:
        if basic[i] != '':
            timepoint.append(fomat_date_str(basic[i]))
    if basic['champion_schedule']['enable'] and basic['champion_schedule']['begin_time'] != '':
        timepoint.append(fomat_date_str(basic['champion_schedule']['begin_time']))

    # 主页竞猜阶段
    for i in basic['stage']:
        stage_index = i['index']
        for j in time_field_list:
            if i[j] != '':
                timepoint.append(fomat_date_str(i[j]))
        if basic['normal_schedule']['enable'] and i['enable_normal']:
            normal_data = normal[str(stage_index)]
            for z in normal_data['single']:
                for j in time_field_list:
                    if z[j] != '':
                        timepoint.append(fomat_date_str(z[j]))
    timepoint = list(set(timepoint))
    timepoint.sort()

    cur_time = int(time.time())
    new_filename = 'betting_event_timeline' + "_" + str(cur_time) + ".xlsx"
    current_dir = os.path.dirname(os.path.realpath(__file__)) + "/tmp_data"
    # current_dir = "./tmp_data"

    # writer = pd.ExcelWriter('./tmp_data/betting_event_timeline.xlsx')
    writer = pd.ExcelWriter(current_dir + "/" + new_filename)
    print(current_dir + "/" + new_filename)
    data = {"时间戳": deepcopy(timepoint)}
    data['原始时间'] = []
    for i in timepoint:
        data['原始时间'].append(fomat_timestamp(i))
    for i in range(len(data['时间戳'])):
        data['时间戳'][i] = str(data['时间戳'][i])

    data['竞猜主页总排期'] = []
    for i in timepoint:
        tmp = ''
        for j in time_field_list:
            if fomat_date_str(basic[j]) == i:
                if tmp == '':
                    tmp = tmp + time_field_map[j]
                else:
                    tmp = tmp + '/' + time_field_map[j]
        data['竞猜主页总排期'].append(tmp)
    for stage_i in range(len(basic['stage'])):
        stage_name = '竞猜主页阶段-' + str(stage_i + 1)
        data[stage_name] = []
        for i in timepoint:
            tmp = ''
            for j in time_field_list:
                if fomat_date_str(basic['stage'][stage_i][j]) == i:
                    if tmp == '':
                        tmp = tmp + time_field_map[j]
                    else:
                        tmp = tmp + '/' + time_field_map[j]
            data[stage_name].append(tmp)
    if basic['normal_schedule']['enable']:
        data['普通竞猜总排期'] = []
        for i in data['竞猜主页总排期']:
            data['普通竞猜总排期'].append(i)
        for stage_i in range(len(basic['stage'])):
            stage_index = basic['stage'][stage_i]['index']
            if basic['stage'][stage_i]['enable_normal']:
                normal_data = normal[str(stage_index)]
                stage_name = '普通竞猜阶段-' + str(stage_i + 1)
                data[stage_name] = []
                for i in timepoint:
                    tmp = ''
                    if fomat_date_str(basic['stage'][stage_i]['forecast_time']) == i:
                        if tmp == '':
                            tmp = tmp + 'f/b'
                        else:
                            tmp = tmp + '/' + 'f/b'
                    if fomat_date_str(basic['stage'][stage_i]['close_time']) == i:
                        if tmp == '':
                            tmp = tmp + 'e/c'
                        else:
                            tmp = tmp + '/' + 'e/c'
                    data[stage_name].append(tmp)
                for single_i in range(len(normal_data['single'])):
                    single_stage_name = '普通单局竞猜-' + str(stage_i + 1) + '-' + str(single_i + 1)
                    data[single_stage_name] = []
                    single_data = normal_data['single'][single_i]
                    for i in timepoint:
                        tmp = ''
                        for j in time_field_list:
                            if fomat_date_str(single_data[j]) == i:
                                if tmp == '':
                                    tmp = tmp + time_field_map[j]
                                else:
                                    tmp = tmp + '/' + time_field_map[j]
                        data[single_stage_name].append(tmp)

    if basic['champion_schedule']['enable']:
        data['冠军竞猜总排期'] = []
        for i in timepoint:
            tmp = ''
            if fomat_date_str(basic['forecast_time']) == i:
                if tmp == '':
                    tmp = tmp + 'f'
                else:
                    tmp = tmp + '/' + 'f'
            if fomat_date_str(basic['champion_schedule']['begin_time']) == i:
                if tmp == '':
                    tmp = tmp + 'b'
                else:
                    tmp = tmp + '/' + 'b'
            if fomat_date_str(basic['end_time']) == i:
                if tmp == '':
                    tmp = tmp + 'e'
                else:
                    tmp = tmp + '/' + 'e'
            if fomat_date_str(basic['close_time']) == i:
                if tmp == '':
                    tmp = tmp + 'c'
                else:
                    tmp = tmp + '/' + 'c'
            data['冠军竞猜总排期'].append(tmp)

        for stage_i in range(len(basic['stage'])):
            stage_index = basic['stage'][stage_i]['index']
            if basic['stage'][stage_i]['enable_champion']:
                champion_data = champion[str(stage_index)]
                stage_name = '冠军竞猜阶段-' + str(stage_i + 1)
                data[stage_name] = []
                for i in timepoint:
                    tmp = ''
                    for j in time_field_list:
                        if fomat_date_str(basic['stage'][stage_i][j]) == i:
                            if tmp == '':
                                tmp = tmp + time_field_map[j]
                            else:
                                tmp = tmp + '/' + time_field_map[j]
                    data[stage_name].append(tmp)

    data = pd.DataFrame(data)
    data = data.T
    data.to_excel(writer, sheet_name='sheet1', header=None)
    writer.save()

    response = make_response(
        send_from_directory(current_dir, new_filename.encode('utf-8').decode('utf-8'), as_attachment=True))
    response.headers["Content-Disposition"] = "attachment; filename={}".format(
        new_filename.encode().decode('latin-1'))
    response.headers["Cache-Control"] = "no-cache"
    response.headers["max-age"] = 0

    betting_log('schedule_timeline', host, f'schedule={project}, dir={current_dir}, filename={new_filename.encode("utf-8").decode("utf-8")}')

    return response


@betting_event_spider_api.route('/betting_event_spider/<key>', methods=['GET', 'POST'])
def betting_event_spider(key):
    host = request.host
    betting_log('spider', host, f'key={key}')

    def _print(msg, level='info'):
        print(f'[World Cup Spider] [{level}] {msg}', flush=True)

    if key != '2022qatarworldcup':
        _print(f'错误密钥：{key}')
        return jsonify({'status': 200, 'data': {'msg': 'KeyError', 'ret': 0, 'type': 'success', 'env': EVN, 'item': []}})

    request_list = ['11-19', '11-20', '11-21', '11-22', '11-23', '11-24', '11-25', '11-26', '11-27', '11-28', '11-29',
                    '11-30', '12-01', '12-02', '12-03', '12-04', '12-05', '12-06', '12-07', '12-08', '12-09', '12-10',
                    '12-11', '12-12', '12-13', '12-14', '12-15', '12-16', '12-17', '12-18', '12-19']
    time_pd = []

    query_data = WorldCupSehedule.query.all()
    for q in query_data:
        q.isUse = 0

    for req_substr in request_list:
        request_url = f'https://tiyu.baidu.com/api/match/%E4%B8%96%E7%95%8C%E6%9D%AF/live/date/2022-{req_substr}/direction/after?from=self'
        _print(f'substr: {req_substr}, requrl: {request_url}')
        response = requests.post(request_url)
        response = response.json()

        # status '0': 请求成功 '40001': 数据为空
        if response['status'] != '0':
            _print(f'substr: ${req_substr}, status=${response["status"]}, skip this response', level='warning')
            continue

        for data_item in response['data']:
            current_time = data_item['time']
            if current_time in time_pd:
                _print(f'current_time: {current_time} duplicate with existing data, skip this response',
                       level='warning')
                continue
            time_pd.append(current_time)

            for list_item in data_item['list']:
                match_stage = list_item['matchStage']
                if '第1轮' in match_stage:
                    _match_stage = '小组赛第一轮'
                    _match_group = match_stage[:2]
                elif '第2轮' in match_stage:
                    _match_stage = '小组赛第二轮'
                    _match_group = match_stage[:2]
                elif '第3轮' in match_stage:
                    _match_stage = '小组赛第三轮'
                    _match_group = match_stage[:2]
                elif '8决赛' in match_stage:
                    _match_stage = '1/8决赛'
                    _match_group = '-'
                elif '4决赛' in match_stage:
                    _match_stage = '1/4决赛'
                    _match_group = '-'
                elif '半决赛' in match_stage:
                    _match_stage = '半决赛'
                    _match_group = '-'
                elif '季军赛' in match_stage:
                    _match_stage = '季军赛'
                    _match_group = '-'
                elif '决赛' in match_stage:
                    _match_stage = '决赛'
                    _match_group = '-'
                else:
                    raise Exception(f'[World Cup Spider] [ERROR] parse match_stage={match_stage}')

                match_start_time = list_item['startTime']
                match_start_timestamp = fomat_date_str(match_start_time)
                utc_start_timestamp = match_start_timestamp - 60 * 60 * 8
                utc_start_time = fomat_timestamp(utc_start_timestamp)
                _print(
                    f'match_start_time={match_start_time}, utc_start_time={utc_start_time}, match_start_timestamp={match_start_timestamp}, utc_start_timestamp={utc_start_timestamp}')

                status_text = list_item['statusText']
                left_country_name = list_item['leftLogo']['name']
                right_country_name = list_item['rightLogo']['name']
                left_country_score = list_item['leftLogo']['score']
                right_country_score = list_item['rightLogo']['score']

                new_project_data = WorldCupSehedule(
                    stage=_match_stage,
                    group=_match_group,
                    left_country=left_country_name,
                    right_country=right_country_name,
                    left_score=left_country_score,
                    right_score=right_country_score,
                    utc_timestamp=utc_start_timestamp,
                    local_timestamp=match_start_timestamp,
                    status=status_text,
                    createdAt=int(time.time()),
                    isUse=1,
                    show_date=current_time,
                    utc_time=utc_start_time,
                    local_time=match_start_time
                )
                db.session.add(new_project_data)

        time.sleep(1)

    db.session.commit()

    return jsonify({'status': 200, 'data': {'msg': 'finish', 'ret': 0, 'type': 'success', 'env': EVN, 'item': []}})

@betting_event_world_cup_schedule_api.route('/betting_event_world_cup_schedule', methods=['GET', 'POST'])
def betting_event_world_cup_schedule():
    host = request.host
    betting_log('world_cup_schedule', host, f'welcome')

    # show table
    query_result = WorldCupSehedule.query.filter_by(isUse=1).order_by('id').all()
    result = []
    for q in query_result:
        utc_data = q.utc_time
        utc_index = utc_data.find(' ')
        utc_date = utc_data[:utc_index]
        utc_time = utc_data[utc_index + 1:]
        local_data = q.local_time
        local_index = local_data.find(' ')
        local_date = local_data[:local_index]
        local_time = local_data[local_index + 1:]
        result.append({
            "id": q.id,
            "stage": q.stage,
            "group": q.group,
            "left_country": q.left_country,
            "right_country": q.right_country,
            "score": f'{q.left_score} - {q.right_score}',
            "status": q.status,
            "show_date": q.show_date,
            "utc": q.utc_time,
            "local": q.local_time,
            "utc_date": utc_date,
            "utc_time": utc_time,
            "local_date": local_date,
            "local_time": local_time,
            "createdAt": q.createdAt
        })
    result_data = {'status': 200, 'data': {'msg': '', 'ret': 0, 'type': 'success', 'env': EVN, 'item': result}}
    return jsonify(result_data)
